#ifndef _BMPVIEW_JY_H_
#define _BMPVIEW_JY_H_

/**
 * @file bmpview_JY.h
 * @author Joshua Yang
 * @brief Header file for BMP and image processing functions
 *
 * This header file contains the declarations for BMP file I/O operations
 * and various image processing functions, including image rotation, resizing,
 * cropping, and format conversion.
 */

#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus

#include <stdint.h>

#include <stdbool.h>
	// #ifndef bool
	// typedef enum __bool {
	//	false = 0,
	//	true = 1
	// }_bool;
	// #define bool _bool
	// #endif // bool

#ifndef nullptr
#define nullptr (void *)NULL
#endif // nullptr

#define SHOW_BMPVIEW_LOG 0

	typedef enum _bmpViewErrMsg
	{
		BMPVIEW_SUCESS = 0,
		BMPVIEW_FAILED_OPEN_FILE,
		BMPVIEW_FAILED_MEMORY_ALLOCATION,
		BMPVIEW_COLOR_PALETTTE_ERROR,
		BMPVIEW_UNIMPLEMENTED_ERROR,
		BMPVIEW_UNSUPPORTED_ERROR,
		BMPVIEW_INVALID_IMAGE_FORMAT,
		BMPVIEW_ARGUMENTS_ERROR,
		BMPVIEW_OTHER_ERROR
	} bmpViewErrMsg;

	typedef enum _ColorTpye
	{
		GRAY,
		RGB,
		BGR,
		RGBA,
		BGRA,
		ARGB,
		ABGR,
		R_ONLY,
		G_ONLY,
		B_ONLY
	} ColorTpye;

#ifndef CFA_MASK
	typedef struct
	{
		/**
		 * 0: R
		 * 1: G
		 * 2: B
		 */
		uint8_t *buffer;
		uint8_t width;
		uint8_t height;
	} _CFA_MASK;
#define CFA_MASK _CFA_MASK
#endif // !CFA_MASK

	//---- BMP IO ----
	/**
	 * @brief Read a BMP file and retrieve image information.
	 *
	 *
	 * @param[out] dstImage Output image buffer.
	 * @param[out] dstWidth Width of the image.
	 * @param[out] dstHeight Height of the image.
	 * @param[in] file_name Path of the input BMP file.
	 * @param[in] readTo Buffer type to read the image into.
	 * @param[in] isFlipped Specify whether the input BMP file is always flipped.
	 *
	 * @return Error message indicating the success or failure of the operation.
	 */
	bmpViewErrMsg readBMP_JY(uint8_t **dstImage, int *dstWidth, int *dstHeight, const char *file_name, ColorTpye readTo, bool isFlipped);

	/**
	 * @brief Save an image as a BMP file.
	 *
	 * @param[in] srcImage Input image buffer.
	 * @param[in] width Width of the image.
	 * @param[in] height Height of the image.
	 * @param[in] file_name Path to save the BMP file.
	 * @param[in] streamType Buffer type of the source image.
	 * @param[in] isFlipped Specify whether the input BMP file is always flipped.
	 *
	 * @return Error message indicating the success or failure of the operation.
	 */
	bmpViewErrMsg saveBMP_JY(uint8_t *srcImage, int width, int height, const char *file_name, ColorTpye streamType, bool isFlipped);

	/**
	 * @brief Save a color-converted image as a BMP file for the specified panel CFA mask.
	 *
	 * @param[in] srcImage Input image buffer. Gray255 with color conversion
	 * @param[in] width Width of the image.
	 * @param[in] height Height of the image.
	 * @param[in] file_name Path to save the BMP file.
	 * @param[in] cfaMask Panel CFA mask.
	 * @param[in] isFlipped Specify whether the input BMP file is always flipped.
	 *
	 * @return Error message indicating the success or failure of the operation.
	 */
	bmpViewErrMsg saveBMP_DemoKaleido_JY(uint8_t *srcImage, int width, int height, const char *file_name, CFA_MASK cfaMask, bool isFlipped);

	/**
	 * testing
	 */
	bmpViewErrMsg saveBMP_DemoACeP2_JY(uint8_t *srcImage, int width, int height, const char *file_name);

	//---- Image process ----
	/**
	 * @brief Rotate an image 90 degrees clockwise.
	 *
	 * @param[in] image Input image buffer.
	 * @param[in,out] width Width of the image.
	 * @param[in,out] height Height of the image.
	 * @param[in] channel Number of image channels.
	 *
	 * @return Error message indicating the success or failure of the operation.
	 *
	 *   ─╮
	 *  ○ ↓
	 *
	 */
	bmpViewErrMsg img_rotation90_JY(uint8_t *image, int *width, int *height, int channel);

	/**
	 * @brief Rotate an image 180 degrees clockwise.
	 *
	 * @param[in] image Input image buffer.
	 * @param[in,out] width Width of the image.
	 * @param[in,out] height Height of the image.
	 * @param[in] channel Number of image channels.
	 *
	 * @return Error message indicating the success or failure of the operation.
	 *
	 *   ─╮
	 *  ○ │
	 *   ←╯
	 */
	bmpViewErrMsg img_rotation180_JY(uint8_t *image, int *width, int *height, int channel);

	/**
	 * @brief Rotate an image 270 degrees clockwise.
	 *
	 * @param[in] image Input image buffer.
	 * @param[in,out] width Width of the image.
	 * @param[in,out] height Height of the image.
	 * @param[in] channel Number of image channels.
	 *
	 * @return Error message indicating the success or failure of the operation.
	 *
	 *    ─╮
	 * ↑ ○ │
	 * ╰───╯
	 */
	bmpViewErrMsg img_rotation270_JY(uint8_t *image, int *width, int *height, int channel);

	bmpViewErrMsg img_flipped_JY(uint8_t *img, int width, int height, int channel);
	bmpViewErrMsg img_mirror_JY(uint8_t *img, int width, int height, int channel);
	bmpViewErrMsg img_resize_JY(uint8_t **image, int *width, int *height, int newWidth, int newHeight, int channel);
	bmpViewErrMsg img_crop_JY(uint8_t *image, int width, int height, int channel, uint8_t **cropImg, int *cropWidth, int *cropHeight, int left, int top, int right, int bottom);
	bmpViewErrMsg img_padding_JY(uint8_t **image, int *width, int *height, int channel, int left_padding, int top_padding, int right_padding, int bottom_padding);

	//---- PPM/PGM IO ----
	/**
	 * @brief Read an image in PPM format.
	 *
	 * @param[out] dstImage Output RGB image buffer.
	 * @param[out] width Width of the image.
	 * @param[out] height Height of the image.
	 * @param[in] file_name Path of the input image file.
	 * @return Error message indicating the success or failure of the operation.
	 */
	bmpViewErrMsg readPPM_JY(uint8_t **dstImage, int *width, int *height, const char *file_name);

	/**
	 * @brief Save an RGB image as a PPM file.
	 *
	 * @param[in] srcImage Input RGB image buffer.
	 * @param[in] width Width of the image.
	 * @param[in] height Height of the image.
	 * @param[in] file_name Path to save the PPM file.
	 *
	 * @return Error message indicating the success or failure of the operation.
	 */
	bmpViewErrMsg savePPM_JY(uint8_t *srcImage, int width, int height, const char *file_name);

	/**
	 * @brief Read an image in PGM format.
	 *
	 * @param[out] dstImage Output grayscale image buffer.
	 * @param[out] width Width of the image.
	 * @param[out] height Height of the image.
	 * @param[in] file_name Path of the input image file.
	 *
	 * @return Error message indicating the success or failure of the operation.
	 */
	bmpViewErrMsg readPGM_JY(uint8_t **dstImage, int *width, int *height, const char *file_name);

	/**
	 * @brief Save a grayscale image as a PGM file.
	 *
	 * @param[in] srcImage Input grayscale image buffer.
	 * @param[in] width Width of the image.
	 * @param[in] height Height of the image.
	 * @param[in] file_name Path to save the PGM file.
	 *
	 * @return Error message indicating the success or failure of the operation.
	 */
	bmpViewErrMsg savePGM_JY(uint8_t *srcImage, int width, int height, const char *file_name);

	bmpViewErrMsg savePPM_DemoKaleido_JY(uint8_t *srcImage, int width, int height, const char *file_name, CFA_MASK cfaMask);

#ifdef __cplusplus
}
#endif // __cplusplus
#endif // _BMPVIEW_JY_H_
